From eb72f656ae6128891e67422d68ef132bc70393ac Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 16 Aug 2005 15:40:43 +0000 Subject: [PATCH] Fix xtime_lock handling in timer interrupt. There's no need to hold it while doing local VCPU work, and there might be danger of deadlock if we do. Signed-off-by: Keir Fraser --- .../arch/xen/i386/kernel/time.c | 45 +++++++------------ 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c index ea421f080b..4ceded947a 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/time.c @@ -540,17 +540,14 @@ unsigned long profile_pc(struct pt_regs *regs) EXPORT_SYMBOL(profile_pc); #endif -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - */ -static inline void do_timer_interrupt(int irq, void *dev_id, - struct pt_regs *regs) +irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) { s64 delta, delta_cpu; int cpu = smp_processor_id(); struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu); + write_seqlock(&xtime_lock); + do { get_time_values_from_xen(); @@ -582,7 +579,18 @@ static inline void do_timer_interrupt(int irq, void *dev_id, do_timer(regs); } - /* Local CPU jiffy work. */ + if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) { + update_wallclock(); + clock_was_set(); + } + + write_sequnlock(&xtime_lock); + + /* + * Local CPU jiffy work. No need to hold xtime_lock, and I'm not sure + * if there is risk of deadlock if we do (since update_process_times + * may do scheduler rebalancing work and thus acquire runqueue locks). + */ while (delta_cpu >= NS_PER_TICK) { delta_cpu -= NS_PER_TICK; per_cpu(processed_system_time, cpu) += NS_PER_TICK; @@ -590,29 +598,6 @@ static inline void do_timer_interrupt(int irq, void *dev_id, profile_tick(CPU_PROFILING, regs); } - if (shadow_tv_version != HYPERVISOR_shared_info->wc_version) { - update_wallclock(); - clock_was_set(); - } -} - -/* - * This is the same as the above, except we _also_ save the current - * Time Stamp Counter value at the time of the timer interrupt, so that - * we later on can estimate the time of day more exactly. - */ -irqreturn_t timer_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - /* - * Here we are in the timer irq handler. We just have irqs locally - * disabled but we don't know if the timer_bh is running on the other - * CPU. We need to avoid to SMP race with it. NOTE: we don' t need - * the irq version of write_lock because as just said we have irq - * locally disabled. -arca - */ - write_seqlock(&xtime_lock); - do_timer_interrupt(irq, NULL, regs); - write_sequnlock(&xtime_lock); return IRQ_HANDLED; } -- 2.30.2